#include "helper.h"
#include "monitor.h"
#include "reg.h"

extern uint32_t instr;
extern char assembly[80];
extern FILE *trace_fp;
/* invalid opcode */
make_helper(inv) {

	uint32_t temp;
	temp = instr_fetch(pc, 4);

	uint8_t *p = (void *)&temp;
	printf("invalid opcode(pc = 0x%08x): %02x %02x %02x %02x ...\n\n", 
			pc, p[3], p[2], p[1], p[0]);

	printf("There are two cases which will trigger this unexpected exception:\n\
1. The instruction at pc = 0x%08x is not implemented.\n\
2. Something is implemented incorrectly.\n", pc);
	printf("Find this pc value(0x%08x) in the disassembling result to distinguish which case it is.\n\n", pc);

	assert(0);
}

/* stop temu */
make_helper(temu_trap) {

	printf("\33[1;31mtemu: HIT GOOD TRAP\33[0m at $pc = 0x%08x\n\n", cpu.pc);

	temu_state = END;

}

make_helper(eret){
	cpu.pc = cp0.epc;
	cp0.status = 0;
	sprintf(assembly, "eret");
}

static void decode_mfc0_type(uint32_t instr){
	op_src1->type = OP_TYPE_REG;
	op_src1->reg = (instr & 0xf800) >> 11;

	op_src2->type = OP_TYPE_IMM;
	op_src2->imm = instr & 0x7;
	op_src2->val = op_src2->imm;

	op_dest->type = OP_TYPE_REG;
	op_dest->reg = (instr & 0x1f0000) >> 16;
}

make_helper(mfc0){
	decode_mfc0_type(instr);
	reg_w(op_dest->reg) = cp0.gpr[op_src1->reg]._32;
	sprintf(assembly, "mfc0   %s   %s   0x%04x", REG_NAME_CP0(op_dest->reg), REG_NAME_CP0(op_src1->reg), op_src2->val);
    fprintf(trace_fp, "0x%04x     %02d     0x%04x\n", cpu.pc, op_src2->reg, cp0.gpr[op_src1->reg]._32);
}

make_helper(mtc0){
	decode_mfc0_type(instr);
	cp0_w(op_src1->reg) = reg_w(op_dest->reg);
	sprintf(assembly, "mtc0   %s   %s   0x%04x", REG_NAME_CP0(op_dest->reg), REG_NAME_CP0(op_src1->reg), op_src2->val);
    fprintf(trace_fp, "0x%04x     %s     0x%04x\n", cpu.pc, "cp0", reg_w(op_dest->reg));
}
